#ifndef NG_ENGINE_H
#define NG_ENGINE_H

#include <nctl/UniquePtr.h>
#include <nctl/Array.h>

#include <ncine/SceneNode.h>
#include <ncine/IAppEventHandler.h>
#include <ncine/IInputEventHandler.h>
#include <ncine/Font.h>
#include <ncine/Texture.h>
#include <ncine/AudioStreamPlayer.h>
#include <ncine/AudioBufferPlayer.h>

#include <tinyxml2.h>

#include "package.h"

namespace nc = ncine;
namespace nt = nctl;

namespace ng {
  class Engine;

  struct Resource {
    nt::Array<nt::UniquePtr<nc::Font>> font;
    nt::Array<nt::UniquePtr<nc::Texture>> texture;
    nt::Array<nt::UniquePtr<nc::IAudioPlayer>> audio;
  };

  class ResourceMgr {
    public:
      virtual bool addFont(const nt::String &name, nt::UniquePtr<nc::Font> &font);
      virtual void removeFont(const nt::String &name);
      virtual void removeFont(const nc::Font *font);
      virtual void clearFont();
      virtual nc::Font* getFont(const nt::String &name);

      virtual bool addTexture(const nt::String &name, nt::UniquePtr<nc::Texture> &texture);
      virtual void removeTexture(const nt::String &name);
      virtual void removeTexture(const nc::Texture *texture);
      virtual void clearTexture();
      virtual nc::Texture* getTexture(const nt::String &name);

      virtual bool addAudio(const nt::String &name, nt::UniquePtr<nc::AudioStreamPlayer> &player);
      virtual bool addAudio(const nt::String &name, nt::UniquePtr<nc::AudioBufferPlayer> &player);
      virtual void removeAudio(const nt::String &name);
      virtual void removeAudio(const nc::IAudioPlayer *player);
      virtual void clearAudio();
      virtual nc::IAudioPlayer* getAudio(const nt::String &name);
    protected:
      Resource res_;
  };

  class Scene
      : public ncine::SceneNode
      , public ResourceMgr {
    public:
      Scene();
    protected:
      void enterScene();
      void exitScene();
    public:
      virtual nc::Font* getFont(const nt::String &name) override;
      virtual nc::Texture* getTexture(const nt::String &name) override;
      virtual nc::IAudioPlayer* getAudio(const nt::String &name) override;
    public:
      void setAttribute(const char *name, const char *value);
      bool loadXmlFile(const nt::String &file);
      bool loadXmlBuffer(const char *buffer, unsigned len);
      bool loadXml(const tinyxml2::XMLElement *ele);
    protected:
  };

  class Engine
      : public nc::IAppEventHandler
      , public nc::IInputEventHandler
      , public ResourceMgr {
    public:
      Engine();
      virtual ~Engine();
    public:
      Package& package();
      
      void addScene(Scene *scene);
      void removeScene(Scene *scene);
      void changeScene(Scene *scene);
    public:
      void setAttribute(const char *name, const char *value);
      bool loadXmlFile(const nt::String &file);
      bool loadXmlBuffer(const char *buffer, unsigned len);
    protected:
      Package package_;
  };

} // end namespace ng

#endif // NG_ENGINE_H